package com.godenwater.yanyu;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;

import com.godenwater.yanyu.command.UpCommand;
import com.godenwater.yanyu.utils.ByteUtil;
import com.godenwater.yanyu.utils.CRC16Helper;

/**
 * 命令类，针对下发指令时所使用此类进行组装消息
 * 
 * @author admin
 *
 */
public class Command {

	protected byte startBit = Symbol.SOH;
	protected byte[] centerAddr;
	protected byte[] stationAddr;
	protected byte[] funcCode;// 这个不能只用字节
	protected byte[] bodySize;// 报文长度
	protected byte upDown;

	protected byte eof;

	private Command() {
	}

	public Command(byte upDown) {
		this();
		this.upDown = upDown;
	}

	public byte getStartBit() {
		return startBit;
	}

	public void setStartBit(byte startBit) {
		this.startBit = startBit;
	}

	public byte getUpDown() {
		return upDown;
	}

	public void setUpDown(byte upDown) {
		this.upDown = upDown;
	}

	public byte[] getFuncCode() {
		return funcCode;
	}

	public void setFuncCode(byte[] funcCode) {
		this.funcCode = funcCode;
	}

	public byte getEof() {
		return eof;
	}

	public void setEof(byte eof) {
		this.eof = eof;
	}

	public byte[] getCenterAddr() {
		return centerAddr;
	}

	public void setCenterAddr(byte[] centerAddr) {
		this.centerAddr = centerAddr;
	}

	public byte[] getStationAddr() {
		return stationAddr;
	}

	public void setStationAddr(byte[] stationAddr) {
		this.stationAddr = stationAddr;
	}

	/**
	 * 初始化数据报文，只初始化序列值和时间
	 * 
	 * @param sequence
	 * @param date
	 * @return
	 */
	protected void initBase(AbstractBody body, String date) {

		String format = "yyMMddHHmmss";
		if (this.upDown == Symbol.UP) {
			format = "yyMMddHHmm";
		}
		if (StringUtils.isBlank(date)) {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			body.setSendDate(sdf.format(new Date()));
		} else {
			body.setSendDate(date);// 发报时间
		}
	}

	protected IMessageHeader buildHeader(IMessageBody body) {
		// 报文头
		YYMessageHeader header = new YYMessageHeader();

		YYBuilder.newStartBit(header);
		YYBuilder.newCenterAddr(header, centerAddr); // 1-255,按十六进制数输入,从配置文件中读取
		YYBuilder.newStationAddr(header, this.stationAddr);// 从配置文件中读取
		YYBuilder.newFuncCode(header, this.funcCode);
		YYBuilder.newBodySize(header, body.getLength() + 3);// 加3是为了把报文结束符和校验位给加进去

		return header;
	}

	public byte[] builderCrc(IMessage message) {

		StringBuffer sb = new StringBuffer();
		sb.append(toHexString(message.getHeader()));
		sb.append(ByteUtil.toHexString(message.getBody().getContent())
				.toUpperCase());
		sb.append(ByteUtil.toHexString(message.getEOF()));

		String crc = CRC16Helper.crc16Check(sb.toString());

		return ByteUtil.HexStringToBinary(crc);

	}

	protected IMessage buildMessage(IMessageBody body) {

		try {
			IMessage message = new YYMessage();
			message.setHeader(buildHeader(body));
			message.setBody(body);
			message.setEOF(this.eof);
			message.setCRC(builderCrc(message));

			return message;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 在这个方法中需要添加对ASC和HEX两种报文的转议
	 * 
	 * @param header
	 * @return
	 */
	public String toHexString(IMessageHeader header) {
		StringBuffer sb = new StringBuffer(header.getLength());
		sb.append(ByteUtil.toHexString(header.getStartBit()));
		if (Symbol.UP == this.upDown) {
			sb.append(ByteUtil.toHexString(header.getCenterAddr()));
			sb.append(ByteUtil.toHexString(header.getStationAddr()));
		} else {
			sb.append(ByteUtil.toHexString(header.getStationAddr()));
			sb.append(ByteUtil.toHexString(header.getCenterAddr()));
		}
		sb.append(ByteUtil.toHexString(header.getFuncCode()));
		sb.append(ByteUtil.toHexString(header.getBodySize()));

		return sb.toString();
	}

	public String printHexString(IMessage message) {
		StringBuffer sb = new StringBuffer();
		sb.append(toHexString(message.getHeader()).toUpperCase());
		sb.append(ByteUtil.toHexString(message.getBody().getContent())
				.toUpperCase());
		sb.append(ByteUtil.toHexString(message.getEOF()).toUpperCase());
		sb.append(ByteUtil.toHexString(message.getCRC()).toUpperCase());
		return sb.toString();
	}

	public static void main(String[] args) {
		UpCommand cmd = new UpCommand();
		cmd.setEof(Symbol.ETX);
		cmd.setFuncCode(new byte[] { (byte) 0x2F });

		IMessage message = cmd.sendMessage(null);

		System.out.println(">> hex " + cmd.printHexString(message));

		String hexStr = cmd.toHexString(message.getHeader());
		System.out.print(">> hex " + hexStr.toUpperCase());
		System.out.print(""
				+ ByteUtil.toHexString(message.getBody().getContent()));
		System.out.print("" + ByteUtil.toHexString(message.getEOF()));
		System.out.print("" + ByteUtil.toHexString(message.getCRC()));
	}

}
